#ifndef FUZZYCLASSIFIER_H
#define FUZZYCLASSIFIER_H

#include <vector>
#include <boost/tr1/unordered_map.hpp>
#include <string>

#include "Classifier.h"
#include "viewer.h"

namespace fc
{

using namespace std;
using namespace boost;


class FuzzyClassifier : public Classifier
{
    friend class Viewer;
    int FS;

    typedef vector<FuzzySet> FuzzySets;
    typedef unordered_map<string, Result> Rules;
    vector<Rules> rules_;
    vector<FuzzySets> sets_;
    vector<double> min_;
    vector<double> max_;
    int attributes_;
    vector<AttributeWeight> attributesWeights_;
public:
    FuzzyClassifier(int fuzzy_sets);
    void setTrainingData ( const vector<Example> & data, int attributes );
    Result classify( const vector< double >& example ) const;
private:
    void cleanUp();

    void createSets(const vector< Example >& data);
    void createRules(const vector< Example >& data);
    void measureAttributes(const vector< Example > & data);
    void updateExtremes(const vector< Example >& data);
    void putRule(const RuleInfo & ruleInfo, int attributes);
    RuleInfo createRuleInfo(const Example& example, int attributes) const;
    vector< pair< string, double > > createKeys ( const vector< double >& attributes ) const;
    double measure ( double weight1, double weight2 ) const;
    void createKeysR ( const vector< double >& attributes,
                       int position,
                       const std::string& prefix,
                       double currentWeight,
                       vector< std::pair< string, double > >& keys ) const;
    vector< pair<int, double> > findSets ( double value, int attributeNr ) const;
    pair<int, double> bestFitSet(double value, int attributeNr ) const;
    string ruleToStr(RuleInfo rule) const;

    double measureAttribute(const vector< Example > & data, int attributeNr) const;
    void normalizeAttributesWeights();
    string antecedent(string key, int attributes) const;
};

}

#endif // FUZZYCLASSIFIER_H
